#include "EventLoop.h"
#include <sys/eventfd.h>
#include <unistd.h>
#include <fcntl.h>
#include "Logger.h"
#include <errno.h>
#include "Poller.h"
#include "Channel.h"
#include <memory>

//防止一个线程创建多个EventLoop
__thread EventLoop *t_loopInThisThread = nullptr;

const int KPollTimesMs = 10000; //定义默认Poller Io复用接口的超时时间

//创建wakeupfd，用来唤醒subReactor
int createEventfd() {
    int evtfd =::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd < 0) {
        LOG_FATAL("eventfd error: %d\n", errno);
        abort();
    }
    return evtfd;

}

EventLoop::EventLoop() 
: looping_(false)
, quit_(false)
, callingPendingFunctors_(false)
, threadId_(CurrentThread::tid())
, poller_(Poller::newDefaultPoller(this))
, wakeupFd_(createEventfd())
, wakeupChannel_(new Channel(this, wakeupFd_))

{
    if (t_loopInThisThread) {
        // LOG_FATAL
        exit(-1);
    } else {
        t_loopInThisThread = this;
    }
    wakeupChannel_->setReadCallback(std::bind(&EventLoop::handleRead, this));

    // 每一个eventloop都将监听wakeupchannel的EPOLL读事件了
    wakeupChannel_->enableReading();

}
EventLoop::~EventLoop() {
    wakeupChannel_->disableAll();
    wakeupChannel_->remove();
    ::close(wakeupFd_);
    t_loopInThisThread = nullptr;
}

// 开启事件循环
void EventLoop::loop() {
    looping_ = true;
    quit_ = false;
    LOG_INFO("Event loop %p start\n", this);
    while (!quit_) {
        activeChannels_.clear(); // 调用EpollPooler::poll后存储发生io事件的channel对象

        // 监听两类fd：通信用的cfd ，还有就是wakeupfd用来唤醒线程的
        pollReturnTime_ = poller_->poll(KPollTimesMs, &activeChannels_);
        
        for (Channel *channel : activeChannels_) {
            // poller监听的channel发生事件了，然后上报给eventloop存在activeChannels_中，
            // eventloop再通知channel处理相应事件
            channel->handleEvent(pollReturnTime_);
        }

        /*  
        io线程：mainloop accept 得到通信的fd和channel绑定
        mainloop 事先注册回调cb需要subloop执行 wakeup唤醒subloop后执行mainloop注册的cb
        */
        doPendingFunctors(); //执行当前eventloop事件循环需要处理的回调操作？？
    }
    looping_ = false;

}
// 退出事件循环
/**
 * @brief 看不懂
 * 
 */
void EventLoop::quit() {
    quit_ = true;
    if (!isInLoopThread()) { //其它线程调用quit，唤醒io线程
        wakeup(); //若线程阻塞在loop的poller->poll上时，唤醒线程，执行后续操作，最后quit_ = true跳出循环
    }
}

//直接在我当前的loop中执行cb
void EventLoop::runInLoop(Functor cb) {
    if (isInLoopThread()) {
        cb();
    } else {
        queueInLoop(std::move(cb));
    }
}

// 把cb放入队列中，唤醒loop所在的线程执行cb
void EventLoop::queueInLoop(Functor cb) {
    {
        std::unique_lock<std::mutex> lock(mutex_);
        pendingFunctors_.emplace_back(cb);
    }
    // 唤醒相应的需要执行上面回调操作的loop的线程
    // || callingPendingFunctors_的意思是当前loop正在doPendingFunctors()，
    // 但是loop有有了新的回调，所以防止下一轮循环阻塞在poll上，就需要唤醒
    if (!isInLoopThread() || callingPendingFunctors_) {
        wakeup(); // 唤醒loop所在线程
    }
}


void EventLoop::handleRead() {
    uint64_t one = 1;
    ssize_t n = read(wakeupFd_, &one, sizeof(one));
    if (n != sizeof one) {
        // error
    }
}

// 唤醒loop所在线程, 向wakeupfd写数据唤醒当前loop线程去做事，防止其阻塞在loop上，
void EventLoop::wakeup() // main reactor唤醒 sub reactor, 往Wakeupfd写来唤醒
{
    uint64_t one = 1;
    ssize_t n = write(wakeupFd_, &one, sizeof one);
    if (n != sizeof one) {
        //ERROR
        LOG_ERROR("wakeup loop thread faild\n");
    }
}
        
// eventloop的方法调用poller的方法
void EventLoop::updateChannel(Channel* channel) {
    poller_->updateChannel(channel);
}
void EventLoop::removeChannel(Channel* channel) {
    poller_->removeChannel(channel);
}
bool EventLoop::hasChannel(Channel* channel) {
    return poller_->hasChannel(channel);
}
        
void EventLoop::doPendingFunctors() //执行回调
{
    std::vector<Functor> functors;
    callingPendingFunctors_ = true;
    {
        std::unique_lock<std::mutex> lock(mutex_);
        functors.swap(pendingFunctors_);
    }
    for (const Functor& functor : functors) {
        functor(); // 调用当前loop需要执行的回调
    }
    callingPendingFunctors_ = false;
}